<?php
# ***** BEGIN LICENSE BLOCK *****
# This file is part of "myWiWall".
# Copyright (c) 2007-2008 CRP Henri Tudor and contributors.
# All rights reserved.
#
# "myWiWall" is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as published by
# the Free Software Foundation.
# 
# "myWiWall" is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with "myWiWall"; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# ***** END LICENSE BLOCK *****


/**
 * The Engine module gathers the actions providing the access to the server-side part of the
 * Widget Engine. These actions are services. These services are requested through XML HTTP
 * REQUEST by the client-side part of the Widget Engine.
 * 
 * Services that return information through THE XML HTTP RESPONSE usually provides a parameter
 * allowing you to describe an output format. This output format can be json or xml.
 *
 * @author Laurent Haan <laurent.haan@gmail.com>
 * @author J�r�me Bogaerts <jerome.bogaerts@gmail.com>
 * @package mywiwall.actions
 */
class Engine
{
	/**
	 * This action should be requested through XML HTTP REQUEST in order to save the state of
	 * the widget wall of the logged user when a particular event occurs at the client-side.
	 * 
	 * These events could be :
	 * - 'add' 		: A widget has been inserted in the widget wall of the user.
	 * - 'move' 	: A widget has been moved to an other position in the widget wall of the user.
	 * - 'delete'	: A widget has been removed from the widget wall of the user.
	 * - 'minimize'	: A widget has been minimized in the widget wall of the user.
	 * 
	 * Parameters $c_0, $c_1 and $c_2 represent the information about the widgets'position in a column of the
	 * user interface. Information about a column is organized as a list of string. Each string in the array
	 * represents a widget string identifier e.g 'widgetContainer_miniClock'. The index of the string in the array
	 * represents the position of the widget in the colum. For instance, the array('widgetContainer_miniClock', 'widgetContainer_tagCloud')
	 * explains that the 'miniClock' widget is at the top of the column and that 'tagCloud' is just beneath it.
	 *
	 * @param string $widgetId The identifier of the widget that is concerned by the triggered event. (not used in each case)
	 * @param string $action The event that occured in the widget wall of the user. The value of this parameter must be 'add', 'move', 'delete' or 'minimize'.
	 * @param array $c_0 The left column information about the widget wall of the user.
	 * @param array $c_1 The central column information about the widget wall of the user.
	 * @param array $c_2 The right column information about the widget wall of the user.
	 */
	public function updateInterface($widgetId, $action, $c_0, $c_1, $c_2)
	{
		$columns = array($c_0, $c_1, $c_2);
		
		if (!Auth::isAuth())
			throw new ServiceException(MwwException::ACTION, 'updateInterface', ServiceException::SERV_AUTH);
		
		// Update the action following the requested action.
		switch($action)
		{ 
			case 'add':
		
				UserInterface::insertWidget(Auth::getUserId(), 
											$widgetId, 
											self::buildWidgetStates($columns));
				break;
				
			case 'move':
				UserInterface::update(Auth::getUserId(),
									  self::buildWidgetStates($columns));
				break;
				
			case 'delete':
				UserInterface::deleteWidget(Auth::getUserId(),
											$widgetId,
											self::buildWidgetStates($columns));
				break;
			
			case 'minimize':
				UserInterface::minimizeWidget(Auth::getUserId(),
											  $widgetId);
				break;
			default:
				throw new BadArgumentException(MwwException::ACTION, 'Unknown action when trying to update user\'s interface.');
		}
	}
	
	/**
	 * This action, acting as a service, should be requested through  an XML HTTP REQUEST in order to
	 * retrieve a list of the Widget categories contained in the persistant data of the application.
	 * 
	 * The output format is JSON and the result is simply written in the XML HTTP RESPONSE.
	 * TODO The getCategories action seems to be never used in any case. Verify it, and delete it is useless.
	 */
	public function getCategories()
	{
		if (!Auth::isAuth())
			throw new ServiceException(MwwException::ACTION, 'getCategories', ServiceException::SERV_AUTH);
			
		$categories = Categories::retrieveCategories('json', $withEmpty = true);
		echo $categories;
	}
	
	/**
	 * The getInterface action, acts as a service and should be requested through an XML HTTP REQUEST
	 * in order to retrieve information about the interface of logged in user. The output format should be
	 * 'json' or 'xml'. The output is simply written in the XML HTTP RESPONSe.
	 *
	 * @param string $format The output format that will be used in the XML HTTP RESPONSE.
	 */
	public function getInterface($format)
	{
		if (!Auth::isAuth())
			throw new ServiceException(MwwException::CONTROLLER, 'getInterface', ServiceException::SERV_AUTH);
		
		
		$interface = UserInterface::retrieve(Auth::getUserId(), $format);
		echo $interface;
	}
	
	/**
	 * The getManifest action, acts as a service and should be requested through an XML HTTP REQUEST
	 * in order to retrieve a widget's manifest (with palette extension) for a user. 
	 * Actually, the XML manifest will contain the preferences of the widget for user requesting this service through its user-agent.
	 *
	 * The manifest will be simply written in the XML HTTP RESPONSE.
	 * 
	 * @param string $widget The widget's identifier.
	 */
	public function getManifest($widget)
	{
		if (!Auth::isAuth())
			throw new ServiceException(MwwException::CONTROLLER, 'getManifest', ServiceException::SERV_AUTH);
		
			
		$manifest = UserInterface::retrieveWidgetManifest(Auth::getUserId(), $widget);
		
		// XML Header sent and output to the user-agent.
		header('Content-Type: text/xml');
		echo $manifest;
	}
	
	/**
	 * The getTags action acts as a service and should be requested through an XML HTTP GET Rrequest in order
	 * to retrieve tags in a json format. The result will be simply written in the HTTP Response.
	 * 
	 * This action can be triggered in different manners :
	 * - by specifying the 'cloud' GET parameter -> in this way you will get the entire list of tags
	 *   available on the system and their counters (occurences of the tag).
	 * - by specifying the 'q' GET parameter -> in this way you will execute a search in the tags
	 *   stored in the system (this query is in fact a SQL LIKE statement on tag names).
	 * - by specifying the 'widget' GET parameter -> in this way you will get the tags relevant
	 *   to a single widget string identifier.
	 *
	 *
	 * @param string $q The tag name you want to search in the persistent data. 
	 * @param integer $cloud If set to a positive value, tells the method behavior to list all tags and their counters. 
	 * @param string $widget The widget string identifier that you want find the tags.
	 */
	public function getTags($q, $cloud, $widget)
	{
		if (!Auth::isAuth())
			throw new ServiceException(MwwException::ACTION, 'getTags', ServiceException::SERV_AUTH);
		
		// this returns the tags and their counter.
		if (isset($cloud))
			// Returns all tags and their counter.
			echo Tags::retrieveAllTags($cloud, 'json');
			
		else if (isset($widget))
			// Returns all tag identifiers for a given widget.
			echo Tags::retrieveWidgetTags($widget, 'json');

		else
		{
			// Return all tags LIKE (a SQL-LIKE token is used internally) for a given prefix.
			foreach (Tags::searchForTags($q) as $label)
				echo $label."\r\n";
		}
	}
	
	/**
	 * The getWidgetList action acts as a service and should be triggered through an XML HTTP GET Request in order
	 * to get the lists of widgets that are available for the user-agent's owner (the currently logged in user).
	 *
	 * @param string $format The output format that will be written in the HTTP Response. It must 'json' or 'xml'.
	 * @param string $tag If set, will search the widgets to put in the resulting output by tag name.
	 * @param integer $cat If set, will search the widgets to put in the resulting output by category id.
	 */
	public function getWidgetList($format, $tag = null, $cat = null)
	{
		if (!Auth::isAuth())
			throw new ServiceException(MwwException::CONTROLLER, 'getWidgetList', ServiceException::SERV_AUTH);
			
		
		if (isset($tag)) // We have to search widgets by tag name.
			$widgets = Widgets::retrieveWidgetListByTag(Auth::getUserId(), $tag, Auth::getUserLevel(), $format);
		
		else if (isset($cat)) // We have to search widgets by category id.
			$widgets = Widgets::retrieveWidgetListByCategory(Auth::getUserId(), $cat, Auth::getUserLevel(), $format);
		
		else // We have to get all widgets relevant to the authenticated user.
			$widgets = Widgets::retrieveWidgetList(Auth::getUserId(), Auth::getUserLevel(), $format);
			
		echo $widgets;
	}
	
	/**
	 * The updatePreferences action acts as a service and should be triggered through an XML HTTP GET Request
	 * in order to update the preferences of a widget for the user that is currently authenticated .
	 *
	 * @param string $widgetId The widget string database identifier.
	 * @param unknown_type $widgetTags The tags associated to the widget by the user. Each tag is separated by a blank character (' ').
	 */
	public function updatePreferences($widgetId, $widgetTags = null)
	{
		if (!Auth::isAuth())
			throw new ServiceException(MwwException::ACTION, 'updatePreferences', ServiceException::SERV_AUTH);
		
		UserInterface::updateWidgetPreferences(Auth::getUserId(), 
											   $widgetId, 
											   self::buildWidgetPreferences($_POST),
											   self::buildWidgetTags($widgetTags));
		
	}
	
	public function i18n($messages)
	{
		if (!Auth::isAuth())
			throw new ServiceException(MwwException::ACTION, 'I18N', ServiceException::SERV_AUTH);
		
		$translations = array();
		$messages = json_decode(html_entity_decode($messages, ENT_QUOTES, 'UTF-8'));
		
		foreach($messages as $msg)
			$translations[] = array('original' 		=> $msg,
							  		'translated'	=> __($msg));
			
		echo json_encode($translations);
	}
	
	public function isUsingAuthentication($widgetId)
	{
		echo json_encode(Widgets::isUsingAuthentication($widgetId));
	}
	
	private function buildWidgetPreferences(array $getParams)
	{
		$data = array();
		foreach($getParams as $key => $value)
		{
			if ($key == 'widgetId' || $key == 'widgetTags')
				continue;
				
			$data[$key] = $value;
		}
		
		return $data;
	}
	
	private function buildWidgetTags($stringTags)
	{
		if ($stringTags == null)
			return array();
		
		$tags = explode(' ', $stringTags);
		
		foreach ($tags as $tag)
		{
			if (!empty($tag))
				$tagArray[] = $tag;
		}
		
		return $tagArray;
	}
	
	private function buildWidgetStates($columns)
	{
		$states = array();
		for ($c = 0; $c < 3; $c++)
		{
			if (isset($columns[$c]))
			{
				for($i = 0; $i < count($columns[$c]); $i++)
				{
					$states[] = array('column' => $c,
								  	  'position' => $i,
								  	  'widgetid' => substr($columns[$c][$i], strpos($columns[$c][$i], '_') + 1));
				}
			}
		}
		
		return $states;
	}
	
	public static function getWidgetsByCategory($categoryId, $offset, $count)
	{
		$userLevel = Auth::getUserLevel();
		$userId = Auth::getUserId();
		$format = 'raw';
		
		if ($categoryId == 'null')
			$categoryId = null;
		
		$jsonWidgets = Widgets::retrieveWidgetListByCategory($userId, $categoryId, $userLevel, $format);
		$chunkedWidgets = array();
		
		for ($i = $offset; ($i < ($offset + $count)) && ($i < count($jsonWidgets)); $i++)
			$chunkedWidgets[] = $jsonWidgets[$i];
			
		echo json_encode($chunkedWidgets);
	}
}
?>